package clusterConfig

import (
	"context"
	"devops-super/api"
	"devops-super/api/configs/v1"
	"devops-super/internal/dao"
	"devops-super/internal/model/entity"
	"devops-super/internal/service"
	"errors"
	"fmt"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
)

// sClusterConfig 集群配置逻辑实现
type sClusterConfig struct{}

func init() {
	service.RegisterClusterConfig(New())
}

// New 创建集群配置逻辑实例
func New() *sClusterConfig {
	return &sClusterConfig{}
}

// Add 新增集群配置
func (*sClusterConfig) Add(ctx context.Context, in *entity.AppClusterServerConfig) (err error) {
	// 检查配置键是否已存在
	count, _ := dao.AppClusterServerConfig.Ctx(ctx).
		Where(dao.AppClusterServerConfig.Columns().ServerKey, in.ServerKey).
		Where(dao.AppClusterServerConfig.Columns().GroupName, in.GroupName).
		Where(dao.AppClusterServerConfig.Columns().ConfigKey, in.ConfigKey).
		Count()
	if count > 0 {
		return errors.New("该服务器下的配置组中已存在相同的配置键")
	}

	// 插入集群配置记录
	_, err = dao.AppClusterServerConfig.Ctx(ctx).Insert(in)
	return
}

// Upt 更新集群配置
func (*sClusterConfig) Upt(ctx context.Context, in *entity.AppClusterServerConfig) (err error) {
	// 检查配置是否存在
	configInfo, err := dao.AppClusterServerConfig.Ctx(ctx).WherePri(in.Id).One()
	if err != nil {
		return err
	}
	if configInfo.IsEmpty() {
		return errors.New("集群配置不存在")
	}

	// 检查配置键是否已被其他记录使用
	count, _ := dao.AppClusterServerConfig.Ctx(ctx).
		Where(dao.AppClusterServerConfig.Columns().ServerKey, in.ServerKey).
		Where(dao.AppClusterServerConfig.Columns().GroupName, in.GroupName).
		Where(dao.AppClusterServerConfig.Columns().ConfigKey, in.ConfigKey).
		Where(dao.AppClusterServerConfig.Columns().Id, "!=", in.Id).
		Count()
	if count > 0 {
		return errors.New("该服务器下的配置组中已存在相同的配置键")
	}

	// 更新集群配置记录
	_, err = dao.AppClusterServerConfig.Ctx(ctx).WherePri(in.Id).OmitNilData().Data(in).Update()
	return
}

// GetPageLst 分页获取集群配置列表
func (*sClusterConfig) GetPageLst(ctx context.Context, in *api.PageLstReq) (out *api.PageLstRes[*entity.AppClusterServerConfig], err error) {
	out = &api.PageLstRes[*entity.AppClusterServerConfig]{}
	m := dao.AppClusterServerConfig.Ctx(ctx).Safe(true)

	// 服务器key筛选
	if serverKey := in.Wheres.Get("serverKey"); !serverKey.IsNil() {
		m = m.Where(dao.AppClusterServerConfig.Columns().ServerKey, serverKey.Int64())
	}

	// 配置组名筛选
	if groupName := in.Wheres.Get("groupName"); !groupName.IsNil() {
		m = m.Where(dao.AppClusterServerConfig.Columns().GroupName+" like ? ", "%"+groupName.String()+"%")
	}

	// 配置键筛选
	if configKey := in.Wheres.Get("configKey"); !configKey.IsNil() {
		m = m.Where(dao.AppClusterServerConfig.Columns().ConfigKey+" like ? ", "%"+configKey.String()+"%")
	}

	// 分页查询
	err = m.Offset(in.Offset()).Limit(in.Limit()).OrderDesc(dao.AppClusterServerConfig.Columns().Id).ScanAndCount(&out.List, &out.Total, false)
	return
}

// Del 删除集群配置
func (*sClusterConfig) Del(ctx context.Context, id int64) (err error) {
	// 检查配置是否存在
	count, _ := dao.AppClusterServerConfig.Ctx(ctx).WherePri(id).Count()
	if count == 0 {
		return errors.New("集群配置不存在")
	}

	// 删除集群配置
	_, err = dao.AppClusterServerConfig.Ctx(ctx).WherePri(id).Delete()
	return
}

// GetOne 获取单条集群配置
func (*sClusterConfig) GetOne(ctx context.Context, id int64) (out *entity.AppClusterServerConfig, err error) {
	out = new(entity.AppClusterServerConfig)
	err = dao.AppClusterServerConfig.Ctx(ctx).WherePri(id).Scan(&out)
	return
}

// GetOptions 获取集群配置选项
func (*sClusterConfig) GetOptions(ctx context.Context, in *v1.ClusterConfigGetOptionsReq) (out *v1.ClusterConfigGetOptionsRes, err error) {
	var data []*entity.AppClusterServerConfig
	m := dao.AppClusterServerConfig.Ctx(ctx)

	// 筛选条件
	if in.ServerKey > 0 {
		m = m.Where(dao.AppClusterServerConfig.Columns().ServerKey, in.ServerKey)
	}
	if in.GroupName != "" {
		m = m.Where(dao.AppClusterServerConfig.Columns().GroupName, in.GroupName)
	}

	if err = m.Scan(&data); err != nil {
		return
	}

	out = new(v1.ClusterConfigGetOptionsRes)
	out.Options = make([]*api.FormOptionsItem, 0, len(data))

	// 默认value字段和label字段
	valueField := "id"
	labelField := "configKey"

	// 自定义字段
	if in.FieldKey != "" {
		valueField = in.FieldKey
	}
	if in.FieldLabel != "" {
		labelField = in.FieldLabel
	}

	// 构建选项列表
	for _, v := range data {
		item := &api.FormOptionsItem{}
		// 根据反射获取自定义字段值
		switch valueField {
		case "id":
			item.Value = v.Id
		case "serverKey":
			item.Value = v.ServerKey
		case "configKey":
			item.Value = v.ConfigKey
		case "configValue":
			item.Value = v.ConfigValue
		default:
			item.Value = v.Id
		}

		switch labelField {
		case "configKey":
			item.Label = v.ConfigKey
		case "configValue":
			item.Label = v.ConfigValue
		case "groupName":
			item.Label = v.GroupName
		case "remark":
			item.Label = v.Remark
		default:
			item.Label = v.ConfigKey
		}

		out.Options = append(out.Options, item)
	}

	return
}

// GetGroupConfigs 获取集群配置组
func (*sClusterConfig) GetGroupConfigs(ctx context.Context, in *v1.GetClusterGroupConfigsReq) (out *v1.GetClusterGroupConfigsRes, err error) {
	out = &v1.GetClusterGroupConfigsRes{}

	// 查询配置项
	err = dao.AppClusterServerConfig.Ctx(ctx).
		Where(dao.AppClusterServerConfig.Columns().ServerKey, in.ServerKey).
		Where(dao.AppClusterServerConfig.Columns().GroupName, in.GroupName).
		Order(dao.AppClusterServerConfig.Columns().Id).
		Scan(&out.Configs)
	if err != nil {
		return nil, err
	}

	// 获取最新更新时间
	if len(out.Configs) > 0 {
		latestTime := out.Configs[0].UpdatedAt
		for _, item := range out.Configs {
			if item.UpdatedAt.After(latestTime) {
				latestTime = item.UpdatedAt
			}
		}
		out.UpdatedAt = latestTime.Format("2006-01-02 15:04:05")
	}

	return out, nil
}

// SetGroupConfigs 保存集群配置组
func (*sClusterConfig) SetGroupConfigs(ctx context.Context, in *v1.SetClusterGroupConfigsReq) (err error) {
	// 使用事务确保数据一致性
	tx, err := g.DB().Begin(ctx)
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	// 删除服务器下指定组的现有配置
	_, err = dao.AppClusterServerConfig.Ctx(ctx).
		TX(tx).
		Where(dao.AppClusterServerConfig.Columns().ServerKey, in.ServerKey).
		Where(dao.AppClusterServerConfig.Columns().GroupName, in.GroupName).
		Delete()
	if err != nil {
		return err
	}

	// 批量添加新配置
	for _, item := range in.Configs {
		// 唯一性校验
		exists, err := dao.AppClusterServerConfig.Ctx(ctx).
			TX(tx).
			Where(g.Map{
				dao.AppClusterServerConfig.Columns().ServerKey: in.ServerKey,
				dao.AppClusterServerConfig.Columns().GroupName: in.GroupName,
				dao.AppClusterServerConfig.Columns().ConfigKey: item.ConfigKey,
			}).Count()
		if err != nil {
			return err
		}
		if exists > 0 {
			return errors.New(fmt.Sprintf("配置键 %s 已存在", item.ConfigKey))
		}

		// 插入新配置
		_, err = dao.AppClusterServerConfig.Ctx(ctx).TX(tx).Insert(&entity.AppClusterServerConfig{
			ServerKey:   int64(in.ServerKey),
			GroupName:   in.GroupName,
			ConfigKey:   item.ConfigKey,
			ConfigValue: item.ConfigValue,
			Remark:      item.ConfigDesc,
			CreatedAt:   gtime.Now(),
			UpdatedAt:   gtime.Now(),
		})
		if err != nil {
			return err
		}
	}

	return nil
}
